/*
    var let const
*/

//---------------------------------------------------------------------------------------------------------------------------------------
// var 变量提升
/*
    javaScript引擎，在代码预编译时，javaScript引擎会自动将所有代码里面的var关键字声明的语句都会提升到当前作用域的顶端
*/
function fn11() {
    console.log(a);    // undefined
    var a = 20;
}; 

fn11();


function fn12() {
    console.log(a);    // ReferenceError: Cannot access 'a' before initialization
    let a = 20;
}; 

fn12();


//--------------------------------------------------------------------------------------------------------------------------------------------
// let 禁止重复声明（在相同作用域中）
// const 声明是常量 声明时必须初始化
function fn21() {
    var a = 10;

    var a = 30;

    console.log(a);  // 30
};


function fn22() {
    let b = 10;

    let b = 11;   // SyntaxError: Identifier 'b' has already been declared

    if (true) {
        let b = 12;

        console.log('b1', b);  // 12
    };

    console.log('b2', b);
};


//-------------------------------------------------------------------------------------------------------------------------------------------
// let const 块级作用域：只在当前作用域有效，同一作用域不允许重复声明 不存在变量提升

//-------------------------------------------------------------------------------------------------------------------------------------------
// let const 暂时性死区（TDZ）：let/const 命令会使区块形成封闭的作用域。若在声明之前使用变量，就会报错



//-------------------------------------------------------------------------------------------------------------------------------------------
// var let const 最大的区别
/*
    var在全局作用域声明的变量有一种行为会挂载在window对象上，
    它会创建一个新的全局变量作为全局对象的属性，这种行为说不定会覆盖到window对象上的某个属性，
    而let const声明的变量则不会有这一行为
*/
